/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>

#include "h_stm32_hal_defines.h"
#include "h_stm32_hal_timer.h"
#include "h_stm32_hal_uart.h"
#include "s_freeRTOS_event.h"
#include "temp_msg.h"
#include "h_stm32_iic.h"
#include "s_aht10.h"
#include "h_iic_s_user.h"
#include "h_timer_pwm.h"
#include "h_stm32_hal_spi_norflash.h"

#include "s_user_ds18b20.h"
#include "s_common_loopClock.h"
#include "s_common_message.h"

// #include "usbd_cdc.h"

#include "s_para.h"

#include "inv_mpl_lib_easy_use.h"
#include "mpu9250_quaternio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define S_MSG_QUEUE_DATA_LENGTH         128
#define S_MSG_QUEUE_DEEPTH              20
#define S_MSG_QUEU_WAIT_TIME            10

#define S_SYS_SCANF_MAX_LEN             128
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
// extern uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ];
// extern uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ];
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

IWDG_HandleTypeDef hiwdg;

SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim17;

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

/* Definitions for userTask */
osThreadId_t userTaskHandle;
const osThreadAttr_t userTask_attributes = {
  .name = "userTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 256 * 4
};
/* Definitions for userQueue */
osMessageQueueId_t userQueueHandle;
const osMessageQueueAttr_t userQueue_attributes = {
  .name = "userQueue"
};
/* Definitions for basicTimer */
osTimerId_t basicTimerHandle;
const osTimerAttr_t basicTimer_attributes = {
  .name = "basicTimer"
};
/* USER CODE BEGIN PV */
h_stm32_hal_uart_t sys_uart_t;
s_freeRTOS_event_t user_event_t;
// unsigned char notify_enable = 0U;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_IWDG_Init(void);
static void MX_TIM17_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void);
void start_user_task(void *argument);
void basicTimerCallback(void *argument);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// static void disable_usb_cdc_at(void)
// {
//   USBD_CDC_CfgHSDesc[16] = 0x00;
//   USBD_CDC_CfgFSDesc[16] = 0x00;
// }
#if !EMPL
#include <math.h>
static mpu9250_quaternio_t mpu_t;
#endif
void s_sys_scanf_callback(unsigned char *data, unsigned short len)
{
  // printf("Get data %d\r\n", len);
  s_freeRTOS_event_enqueueFromISR(&user_event_t, s_freeRTOS_event_getUART_evt, data, len, 0);
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  // MX_IWDG_Init();
  MX_TIM17_Init();
  MX_I2C1_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
  h_stm32_hal_uart_printf_init(&huart1);
  printf("System print init success\r\n");
  // HAL_I2C_MspDeInit(&hi2c1);
  // h_iic_s_user_init();
  h_stm32_spi_norFlash_init();
  h_stm32_iic_test();
  s_para_init();

#if EMPL
  inv_init();

  float pitch, roll, yaw;
  int acc;
  while(1)
  {

    signed char r = mpu_mpl_get_data(&pitch, &roll, &yaw, &acc);

    if(!r) 
    {
      printf("%d, %d, %d (%d)\r\n", (int)(pitch * 100), (int)(roll * 100), (int)(yaw * 100), acc);
    }
    
    HAL_Delay(10);
  }
#else
  long gyroBias_t[3] = {0, 0, 0}, accelBias_t[3] = {0, 0, 0};
  float gyroBias[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0};
  float magCalibration[3] = {0, 0, 0}, magbias[3] = {0, 0, 0};  // Factory mag calibration and mag bias

  // long gyrobias[3], accbias[3];

  mpu_t.mpu9250_bus_write = &h_stm32_iic_write;
  mpu_t.mpu9250_bus_read = &h_stm32_iic_read;
  mpu_t.delayms = &HAL_Delay;

  mpu_t.Ascale = AFS_2G;
  mpu_t.Gscale = GFS_250DPS;
  mpu_t.Mscale = MFS_16BITS;
  mpu_t.Mmode = 0x06;

  unsigned char whoiam = mpu9250_quaternio_get_whoiam(&mpu_t);
  printf("Who i am is 0x%02x\r\n", whoiam);

  mpu9250_quaternio_reset(&mpu_t);
  // mpu9250_quaternio_self_test(&mpu_t, gyroBias_t, accelBias_t, 0);

  // inv_dmp_init(accelBias, gyroBias);

  // mpu9250_quaternio_calibrate(&mpu_t, gyroBias, accelBias);
  // gyroBias[0] = gyroBias_t[0] / 131.0;
  // gyroBias[1] = gyroBias_t[1] / 131.0;
  // gyroBias[2] = gyroBias_t[2] / 131.0;

  // accelBias[0] = accelBias_t[0] / 16384.0;
  // accelBias[1] = accelBias_t[1] / 16384.0;
  // accelBias[2] = accelBias_t[2] / 16384.0;

  // printf("gyro bias: %f, %f, %f\r\n", gyroBias[0], gyroBias[1], gyroBias[2]);
  // printf("acc bias: %f, %f, %f\r\n", accelBias[0], accelBias[1], accelBias[2]);

  // printf("gyro bias: %d, %d, %d\r\n", gyroBias[0], gyroBias[1], gyroBias[2]);
  // printf("acc bias: %d, %d, %d\r\n", accelBias[0], accelBias[1], accelBias[2]);


  HAL_Delay(400);

  mpu9250_quaternio_DevInit(&mpu_t);
  mpu9250_quaternio_MagDevInit(&mpu_t, magCalibration);

  // printf("Accelerometer full-scale range = %f  g\n\r", 2.0f*(float)(1<<Ascale));
  // printf("Gyroscope full-scale range = %f  deg/s\n\r", 250.0f*(float)(1<<Gscale));
  printf("Accelerometer full-scale range = %d  g\n\r", 2);
  printf("Gyroscope full-scale range = %d  deg/s\n\r", 250);

  if(mpu_t.Mscale == MFS_14BITS)
  {
    printf("Magnetometer resolution = 14  bits\n\r");
  }
  else if(mpu_t.Mscale == MFS_16BITS)
  {
    printf("Magnetometer resolution = 16  bits\n\r");
  }

  if(mpu_t.Mmode == 2)
  {
    printf("Magnetometer ODR = 8 Hz\n\r");
  }
  else if(mpu_t.Mmode == 6)
  {
    printf("Magnetometer ODR = 100 Hz\n\r");
  }

  mpu9250_quaternio_update_all_res(&mpu_t);

  printf("Accelerometer sensitivity is %f LSB/g \n\r", 1.0f/mpu_t.aRes);
  printf("Gyroscope sensitivity is %f LSB/deg/s \n\r", 1.0f/mpu_t.gRes);
  printf("Magnetometer sensitivity is %f LSB/G \n\r", 1.0f/mpu_t.mRes);
  magbias[0] = +470.;  // User environmental x-axis correction in milliGauss, should be automatically calculated
  magbias[1] = +120.;  // User environmental x-axis correction in milliGauss
  magbias[2] = +125.;  // User environmental x-axis correction in milliGauss

  signed short accelCount[3];  // Stores the 16-bit signed accelerometer sensor output
  signed short gyroCount[3];   // Stores the 16-bit signed gyro sensor output
  signed short magCount[3];    // Stores the 16-bit signed magnetometer sensor output

  float ax, ay, az, gx, gy, gz, mx, my, mz; // variables to hold latest sensor data values 
  float q[4];

  float pitch, yaw, roll;

  int lastUpdate = 0, firstUpdate = 0, Now = 0;

  // gyroBias[0] = gyroBias_t[0] * mpu_t.gRes;
  // gyroBias[1] = gyroBias_t[1] * mpu_t.gRes;
  // gyroBias[2] = gyroBias_t[2] * mpu_t.gRes;

  // accelBias[0] = accelBias_t[0] * mpu_t.aRes;
  // accelBias[1] = accelBias_t[1] * mpu_t.aRes;
  // accelBias[2] = accelBias_t[2] * mpu_t.aRes;

  // printf("gyro bias: %f, %f, %f\r\n", gyroBias[0], gyroBias[1], gyroBias[2]);
  // printf("acc bias: %f, %f, %f\r\n", accelBias[0], accelBias[1], accelBias[2]);

  // while(1);

  firstUpdate = HAL_GetTick();
  lastUpdate = HAL_GetTick();

  while(1)
  {
    if(!mpu9250_quaternio_get_INT_enable(&mpu_t))
    {
      mpu9250_quaternio_read_Acc(&mpu_t, accelCount);
      mpu9250_quaternio_read_Gyro(&mpu_t, gyroCount);
      mpu9250_quaternio_read_Mag(&mpu_t, magCount);

      // Now we'll calculate the accleration value into actual g's
      ax = (float)accelCount[0] * mpu_t.aRes - accelBias[0];  // get actual g value, this depends on scale being set
      ay = (float)accelCount[1] * mpu_t.aRes - accelBias[1];   
      az = (float)accelCount[2] * mpu_t.aRes - accelBias[2];  

      // Calculate the gyro value into actual degrees per second
      gx = (float)gyroCount[0] * mpu_t.gRes - gyroBias[0];  // get actual gyro value, this depends on scale being set
      gy = (float)gyroCount[1] * mpu_t.gRes - gyroBias[1];  
      gz = (float)gyroCount[2] * mpu_t.gRes - gyroBias[2];   

      // Calculate the magnetometer values in milliGauss
      // Include factory calibration per data sheet and user environmental corrections
      mx = (float)magCount[0] * mpu_t.mRes * magCalibration[0] - magbias[0];  // get actual magnetometer value, this depends on scale being set
      my = (float)magCount[1]* mpu_t.mRes * magCalibration[1] - magbias[1];  
      mz = (float)magCount[2]* mpu_t.mRes * magCalibration[2] - magbias[2];   

      // printf("%f, %f, %f\r\n", ax, ay, az);
      // printf("%f, %f, %f\r\n", gx, gy, gz);
      // printf("%f, %f, %f\r\n", mx, my, mz);

      Now = HAL_GetTick();
      deltat = (float)((Now - lastUpdate) / 1000.0f);
      lastUpdate = Now;

      // printf("%d\r\n", Now);


      // printf("%d, %d, %d\r\n", gyroCount[0], gyroCount[1], gyroCount[2]);
      MadgwickQuaternionUpdate(ax, ay, az, gx*PI/180.0f, gy*PI/180.0f, gz*PI/180.0f,  my,  mx, mz, q);

      yaw   = atan2(2.0f * (q[1] * q[2] + q[0] * q[3]), q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3]);   
      pitch = -asin(2.0f * (q[1] * q[3] - q[0] * q[2]));
      roll  = atan2(2.0f * (q[0] * q[1] + q[2] * q[3]), q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]);
      pitch *= 180.0f / PI;
      yaw   *= 180.0f / PI; 
      yaw   -= 13.8f; // Declination at Danville, California is 13 degrees 48 minutes and 47 seconds on 2014-04-04
      roll  *= 180.0f / PI;

      printf("%f %f %f\n\r", yaw, pitch, roll);

    }
  }


#endif
  // temp_msg_init();
  // disable_usb_cdc_at();

  // s_ds18b20_1_init();
  // s_ds18b20_2_init();
  // s_ds18b20_3_init();
  

  // h_timer_pwm_change_channel_duty(pwm_channel_1, 0);
  // h_timer_pwm_change_channel_duty(pwm_channel_2, 0);
  // h_timer_pwm_change_channel_duty(pwm_channel_3, 0);

  // h_timer_pwm_change_frq(800);

  // h_timer_pwm_start_channel(pwm_channel_1);
  // h_timer_pwm_start_channel(pwm_channel_2);
  // h_timer_pwm_start_channel(pwm_channel_3);

  sys_uart_t = h_stm32_hal_uart_init(&huart1, h_stm32_hal_uart_enable, \
    &hdma_usart1_rx, S_SYS_SCANF_MAX_LEN, &s_sys_scanf_callback);
  printf("Call\r\n");


  /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* Create the timer(s) */
  /* creation of basicTimer */
  basicTimerHandle = osTimerNew(basicTimerCallback, osTimerPeriodic, NULL, &basicTimer_attributes);

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* creation of userQueue */
  userQueueHandle = osMessageQueueNew (16, sizeof(unsigned short), &userQueue_attributes);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of userTask */
  userTaskHandle = osThreadNew(start_user_task, NULL, &userTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  user_event_t = s_freeRTOS_event_init(S_MSG_QUEUE_DEEPTH, S_MSG_QUEU_WAIT_TIME, S_MSG_QUEUE_DATA_LENGTH);
  /* USER CODE END RTOS_THREADS */

  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48
                              |RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x2000090E;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief IWDG Initialization Function
  * @param None
  * @retval None
  */
static void MX_IWDG_Init(void)
{

  /* USER CODE BEGIN IWDG_Init 0 */

  /* USER CODE END IWDG_Init 0 */

  /* USER CODE BEGIN IWDG_Init 1 */

  /* USER CODE END IWDG_Init 1 */
  hiwdg.Instance = IWDG;
  hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
  hiwdg.Init.Window = 4095;
  hiwdg.Init.Reload = 4095;
  if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN IWDG_Init 2 */

  /* USER CODE END IWDG_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief TIM17 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM17_Init(void)
{

  /* USER CODE BEGIN TIM17_Init 0 */

  /* USER CODE END TIM17_Init 0 */

  /* USER CODE BEGIN TIM17_Init 1 */

  /* USER CODE END TIM17_Init 1 */
  htim17.Instance = TIM17;
  htim17.Init.Prescaler = 0;
  htim17.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim17.Init.Period = 65535;
  htim17.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim17.Init.RepetitionCounter = 0;
  htim17.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim17) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM17_Init 2 */

  /* USER CODE END TIM17_Init 2 */

}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(States_LED_GPIO_Port, States_LED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SPI_NSS_GPIO_Port, SPI_NSS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : States_LED_Pin */
  GPIO_InitStruct.Pin = States_LED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(States_LED_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SPI_NSS_Pin */
  GPIO_InitStruct.Pin = SPI_NSS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SPI_NSS_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
static unsigned char isUserClockRun = 0U;
static unsigned char basicTimerCount = 0U;

void s_start_clock_util(void)
{
  if(!isUserClockRun) {
    osTimerStart(basicTimerHandle, \
    100); // 1s 
    isUserClockRun = 1U;
  }
  
}
/* USER CODE END 4 */

/* USER CODE BEGIN Header_start_user_task */
/**
  * @brief  Function implementing the userTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_start_user_task */
void start_user_task(void *argument)
{
  /* USER CODE BEGIN 5 */
  s_freeRTOS_event_data que;
  // // H_STM32_USBD_Device_Init();
  // // osTimerStart(basicTimerHandle, 100);
  // // h_stm32_iic_test();
  // // h_iic_user_test();
  // S_AHT10_Init();
  s_start_clock_util();

  // s_common_loopClock_specialEvt_start(s_common_loopClock_uploadData_type);
  h_stm32_hal_uart_startReceive(&sys_uart_t);
  /* Infinite loop */
  for(;;)
  {
    // osDelay(1);
    if(s_freeRTOS_event_ok == s_freeRTOS_event_dequeue(&user_event_t, &que)) {
      switch(que.type) {
        case s_freeRTOS_event_dataUpload_evt:
          // temp_msg_upload();
          break;

        case s_freeRTOS_event_getUART_evt:
        case s_freeRTOS_event_getUSB_evt:
          s_common_message_head(que.data, que.len);
          H_STM32_FREE(que.data);
          que.data = NULL;
          if(que.type == s_freeRTOS_event_getUART_evt)
          {
            h_stm32_hal_uart_restartReceive(&sys_uart_t);
          }
          
          break;

        default:
          break;
      }
    }
  }
  /* USER CODE END 5 */
}

/* basicTimerCallback function */
void basicTimerCallback(void *argument)
{
  /* USER CODE BEGIN basicTimerCallback */
  // unsigned char data[] = "test";
  // printf("%d\r\n", (int)(temp * 1000));
  // printf("%s\n", data);
  
  if(basicTimerCount > 10)
  {
    basicTimerCount = 0;
    HAL_IWDG_Refresh(&hiwdg);
    HAL_GPIO_TogglePin(States_LED_GPIO_Port, States_LED_Pin);
  }
  basicTimerCount++;
  
  // s_common_loopClock_handle();
  // ask_temp_msg_upload();

  // printf("--%d\r\n", STM32_USBD_FS.dev_state);
  // H_STM32_USBD_HID_SendReport(data, strlen(data));
  /* USER CODE END basicTimerCallback */
}

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
